package com.gwctv.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.gwctv.constant.MessageConstant;
import com.gwctv.constant.PasswordConstant;
import com.gwctv.constant.StatusConstant;
import com.gwctv.context.BaseContext;
import com.gwctv.dto.EmployeeDto;
import com.gwctv.dto.EmployeeLoginDTO;
import com.gwctv.dto.EmployeePageDTO;
import com.gwctv.entity.Employee;
import com.gwctv.exception.AccountLockedException;
import com.gwctv.exception.AccountNotFoundException;
import com.gwctv.exception.PasswordErrorException;
import com.gwctv.mapper.EmployeeMapper;
import com.gwctv.result.PageResult;
import com.gwctv.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @Service 作用1：表示此层为业务逻辑处理层
 * 作用2：底层封装@Component注解(控制反转)，将此类的bean对象交给IOC容器管理
 */
@Slf4j
@Service
public class EmployeeServiceImpl implements EmployeeService {
    /**
     * @Autowired 依赖自动注入
     */
    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 此方法用于书写用户是否登录成功的业务逻辑：
     * @param employeeLoginDTO 封装前端登录请求的数据
     */
    @Override
    public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        // 获取前端请求中的username和password数据
        String username = employeeLoginDTO.getUsername();
        String password = employeeLoginDTO.getPassword();
        // 调用dao层方法获取后端查询结果
        Employee employee = employeeMapper.getByUsername(username);

        // 判断账号是否存在，如不存在，将错误向上跑，最终交由全局异常处理器
        if (employee == null) {
            log.info("账号不存在!");
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }

        // 判断密码是否和数据库表中的一致
        // 对前端传进来密码进行MD5加密，然后再与数据库中存储密码进行比对
        password = DigestUtils.md5DigestAsHex(password.getBytes());

        if (!password.equals(employee.getPassword())) {
            log.info("密码错误！");
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        // 判断账号正常有否
        if (StatusConstant.DISABLE == employee.getStatus()) {
            log.info("被锁定！");
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        return employee;
    }

    /**
     * 新增员工
     * @param employeeDto
     */
    @Override
    public void save(EmployeeDto employeeDto){
//        System.out.println("当前线程的id:"+Thread.currentThread().getId());

        Employee employee = new Employee();
        // employeeDto中只封装部分插入数据库表中的数据，因为我们需要将employeeDto对象转换为employee对象，然后在插入数据库表中
        // 使用对象属性copy将employeeDto中属性赋值给employee中同名属性
        BeanUtils.copyProperties(employeeDto,employee);

        // 补全employee中其他属性:
        // 设置账号状态，默认是正常状态 1表示正常 0表示锁定
        employee.setStatus(StatusConstant.ENABLE);
        // 设置密码，默认密码123456 并且使用md5加密
        employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
        // 设置创建时间
//        employee.setCreateTime(LocalDateTime.now());
        // 设置修改时间
//        employee.setUpdateTime(LocalDateTime.now());
        // 设置当前记录创建人id和修改人id
//        employee.setCreateUser(BaseContext.getCurrentId());
//        employee.setUpdateUser(BaseContext.getCurrentId());

        //调用dao持久层，并传入数据
        employeeMapper.inset(employee);
    }

    /**
     * 分页查询
     * @param employeePageDTO 前端传进来的参数
     * @return
     */
    @Override
    public PageResult pageQuery(EmployeePageDTO employeePageDTO){
        //使用PageHelper插件，开始分页查询
        PageHelper.startPage(employeePageDTO.getPage(),employeePageDTO.getPageSize());

        // 分页查询语句
        //注意:PageHelper.startPage(页码, 每页显示数目);  这一句代码，必须放分页查询语句之前，否则会分页不生效。
        //这里由于使用了PageHelper插件实现分页查询，因此我们要遵守其规则，下面我们调用Mapper接口中查询语句方法时返回的数据类型
        //就为Page<E>类型
        Page<Employee> page = employeeMapper.pageQuery(employeePageDTO);

        //将Mapper层分页查询结果分装到PageResult对象中
        List<Employee> records = page.getResult();
//        long total = page.getTotal();
        long total = records.size();
        //构造方法创建PageResult对象
        PageResult pageResult = new PageResult( total,records);

        return pageResult;
    }

    /**
     * 启用禁用员工账号
     * @param status 员工状态参数
     * @param id 员工id
     */
    @Override
    public void startOrStop(Integer status,Long id){
        // update 表名 set status=? where id=?
        // 此处创建实体类，为持久层使用动态sql做准备，这样持久层更新数据更加灵活
        // 方式一创建实体类：
        // Employee employee = new Employee();
        // employee.setStatus(status);
        // employee.setId(id);

        // 方式二创建实体类：
        // 注意：使用构建器创建Employee类的对象，前提是Employee类上加了
        // @Builder注解
        Employee employee = Employee.builder()
                .status(status)
                .id(id)
                .build();

        //调用mapper层
        employeeMapper.update(employee);
    }

    /**
     * 根据id查询员工信息
     * @param id 员工id
     * @return 返回员工信息
     */
    @Override
    public Employee getById(Long id){
        Employee employee = employeeMapper.getById(id);
        // 对传输给前端的密码进行加密
        employee.setPassword("*****");
        return employee;
    }

    /**
     * 根据前端传入信息更新员工信息
     * @param employeeDto controller层传入的数据
     * 注：因为mapper层update方法接收的参数类型为Employee，所以此处我们需要进行类型转化
     */
    @Override
    public void update(EmployeeDto employeeDto){
        Employee employee = new Employee();
        // 将employeeDto中的数据copy到employee对象中
        BeanUtils.copyProperties(employeeDto,employee);
        // 修改employee员工表中的更新时间
//        employee.setUpdateTime(LocalDateTime.now());
        // 修改employee员工表中的更新数据人员
//        employee.setUpdateUser(BaseContext.getCurrentId());
        employeeMapper.update(employee);
    }
}










